package com.mandao.oneplat.boot.dao;

import com.mandao.oneplat.boot.OnePlatConfig;
import com.mandao.oneplat.boot.util.CollectionUtil;
import com.mongodb.Block;
import com.mongodb.client.FindIterable;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Sorts;
import org.apache.commons.lang3.StringUtils;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by sunson on 2017/3/24.
 */
public class OneMongoDao {
    Logger logger = LoggerFactory.getLogger(getClass());

    OneMongoDaoProxy oneMongoDaoProxy;

    public OneMongoDao(OnePlatConfig oneOption) throws IOException {
        oneMongoDaoProxy = new OneMongoDaoProxy(oneOption);
        oneMongoDaoProxy.initDB();
    }

    /**
     * @param entity
     */
    public void saveData(Object entity) {
        if (entity == null) {
            return;
        }
        OneMongoCollection collection = oneMongoDaoProxy.findCollection(entity.getClass());
        collection.getDocument().insertOne(collection.toBsonDocument(entity));
    }

    /**
     * @param entities
     */
    public void saveAllData(List entities) {
        if (CollectionUtil.isEmpty(entities)) {
            return;
        }
        OneMongoCollection collection = oneMongoDaoProxy.findCollection(entities.get(0).getClass());
        List<Document> documents = new ArrayList<>();
        entities.forEach(entity -> documents.add(collection.toBsonDocument(entity)));
        collection.getDocument().insertMany(documents);
    }

    /**
     * 获取集合内所有元素，限制1000条
     *
     * @param clazz
     * @param <T>
     * @return
     */
    public <T> List<T> listData(final Class<T> clazz) {
        return listData(clazz, 1, 1000, null);
    }

    /**
     * 分页获取集合内数据
     *
     * @param clazz
     * @param pageNo
     * @param pageSize 最大1000
     * @param wlang    语言
     * @param <T>
     * @return
     */
    public <T> List<T> listData(final Class<T> clazz, int pageNo, int pageSize, String wlang) {
        OneMongoCollection collection = oneMongoDaoProxy.findCollection(clazz);
        pageSize = Math.min(1000, pageSize);
        FindIterable<Document> findIterable = collection.getDocument().find();
        findIterable.skip((pageNo - 1) * pageSize).limit(pageSize);
        if (AOneBaseLangEntity.class.isAssignableFrom(clazz) && StringUtils.isNotEmpty(wlang)) {
            findIterable.filter(Filters.eq(AOneBaseLangEntity.FIELD_LANG, wlang));
        }
        findIterable.sort(Sorts.descending(AOneBaseEntity.FIELD_CREATE_TIME));
        final List<T> retList = new ArrayList<>();
        findIterable.forEach((Block<Document>) document -> retList.add(collection.toEntity(document, clazz)));
        return retList;
    }

    /**
     * @param hexid
     * @param clazz
     * @param <T>
     * @return
     */
    public <T> T findById(String hexid, Class<T> clazz) {
        OneMongoCollection collection = oneMongoDaoProxy.findCollection(clazz);
        FindIterable<Document> findIterable = collection.getDocument().find(Filters.eq(new ObjectId(hexid)));
        return collection.toEntity(findIterable.first(), clazz);
    }
}
